shiro实现请求拦截并打印日志

您所在的位置:网站首页 明末女诗人 四川 shiro实现请求拦截并打印日志

shiro实现请求拦截并打印日志

2024-07-11 20:39:19| 来源: 网络整理| 查看: 265

传统方式实现HandlerInterceptor

这里代码不但实现了token的认证拦截,也在afterCompletion实现了接口请求日志打印

import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.linlinjava.litemall.core.annotation.VisitorAccessible; import org.linlinjava.litemall.core.enums.CommonCodeEnum; import org.linlinjava.litemall.core.exception.ApplicationException; import org.linlinjava.litemall.core.util.IpUtil; import org.linlinjava.litemall.core.util.JWTVerifierUtil; import org.linlinjava.litemall.db.domain.LitemallUser; import org.linlinjava.litemall.db.domain.UserVo; import org.linlinjava.litemall.db.service.LitemallUserService; import org.linlinjava.litemall.wx.global.GlobalHolder; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.NamedThreadLocal; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class InitInterceptor implements HandlerInterceptor { private static final Log LOGGER = LogFactory.getLog(InitInterceptor.class); @Autowired private LitemallUserService userService; private NamedThreadLocal startTimeThreadLocal = new NamedThreadLocal("StopWatch-StartTime"); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String ip = IpUtil.getIpAddr(request); LOGGER.info("ip:"+ ip +"request:"+ String.format("%s consume millis", request.getRequestURI())); response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Content-Type,Accept,X-Requested-With,token"); long beginTime = System.currentTimeMillis();//1、开始时间 startTimeThreadLocal.set(beginTime); if (request.getMethod().toUpperCase().equals("OPTIONS") || request.getServletPath().contains("ok") || request.getServletPath().contains("api/user/login")) { return true; } // 处理用户 String token = request.getHeader("token"); if (StringUtils.isNotEmpty(token)) { String userCode = ""; try { userCode = (String) JWTVerifierUtil.verify(token).get(2); if (StringUtils.isEmpty(userCode)) { throw new ApplicationException(CommonCodeEnum.NO_ACCESS_RIGHT); } } catch (Exception e) { throw new ApplicationException(CommonCodeEnum.NO_ACCESS_RIGHT); } LitemallUser userInfoEntity = userService.findById(Integer.valueOf(userCode)); if (userInfoEntity == null) { throw new ApplicationException(CommonCodeEnum.NO_ACCESS_RIGHT); } UserVo userInfo = new UserVo(); BeanUtils.copyProperties(userInfoEntity, userInfo); GlobalHolder.setCurrentLoginUser(userInfo); } else { HandlerMethod handlerMethod = (HandlerMethod) handler; VisitorAccessible annotation = handlerMethod.getMethodAnnotation(VisitorAccessible.class); if (annotation == null) { throw new ApplicationException(CommonCodeEnum.NO_ACCESS_RIGHT); } } return true; } /** * 在业务处理器处理请求执行完成后,生成视图之前执行的动作 可在modelAndView中加入数据,比如当前时间 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } /** * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等 * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion() 处理写session工作 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { try { long endTime = System.currentTimeMillis();//2、结束时间 long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间) long consumeTime = endTime - beginTime;//3、消耗的时间 String ip = IpUtil.getIpAddr(request); LOGGER.info("ip:"+ ip +"request:"+ String.format("%s consume %d millis", request.getRequestURI(), consumeTime)); } catch (Exception e) { e.printStackTrace(); } GlobalHolder.removeCurrentLoginUser(); } } shiro中AdviceFilter实现请求日志打印

AdviceFilter 提供了 AOP 的功能,其实现和 SpringMVC 中的 Interceptor 思想一样

public class MyAdviceFilter extends AdviceFilter { @Override protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { System.out.println("====预处理/前置处理"); return true;//返回 false 将中断后续拦截器链的执行 } @Override protected void postHandle(ServletRequest request, ServletResponse response) throws Exception { System.out.println("====后处理/后置返回处理"); } @Override public void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception { System.out.println("====完成处理/后置最终处理"); } }

preHandle:进行请求的预处理,然后根据返回值决定是否继续处理(true:继续过滤器链);可以通过它实现权限控制; postHandle:执行完拦截器链之后正常返回后执行; afterCompletion:不管最后有没有异常,afterCompletion 都会执行,完成如清理资源功能。

这里只要在afterCompletion处打印请求日志即可,代码遗留的问题在于如何打印post,put请求的body,先看看完整代码:

import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.shiro.web.servlet.AdviceFilter; import org.springframework.core.NamedThreadLocal; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; /** * @author Cheertan * @date 2020-08-11 */ public class MyAdviceFilter extends AdviceFilter { private static final Log LOGGER = LogFactory.getLog(MyAdviceFilter.class); private NamedThreadLocal startTimeThreadLocal = new NamedThreadLocal("StopWatch-StartTime"); @Override protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { return true; //返回 false 将中断后续拦截器链的执行 } @Override protected void postHandle(ServletRequest request, ServletResponse response) throws Exception { } @Override public void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception { try { long endTime = System.currentTimeMillis(); long consumeTime = endTime; String ip = (request.getRemoteHost()); if (request instanceof HttpServletRequest) { String url = ((HttpServletRequest)request).getRequestURL().toString(); String queryString = ((HttpServletRequest)request).getQueryString(); //String body = IOUtils.toString(((HttpServletRequest)request).getReader()); System.out.println(((HttpServletRequest)request).getMethod()); if (((HttpServletRequest)request).getMethod().equalsIgnoreCase("GET")) { LOGGER.info("ip:" + ip + " request: " + url + "?" + queryString); } else { String body = request.getInputStream().toString(); //body并不能打印出来,待解决,本打算用body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); //但是会报错 LOGGER.info("ip:" + ip + " request: " + url+" body: "+body); } } } catch (Exception e) { e.printStackTrace(); } } }

在shiro配置类里加载自定义的MyAdviceFilter 关键就这段代码:

Map filters = new LinkedHashMap(); filters.put("myAdviceFilter", myAdviceFilter()); shiroFilterFactoryBean.setFilters(filters); import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.realm.Realm; import org.apache.shiro.session.mgt.SessionManager; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.linlinjava.litemall.admin.shiro.AdminAuthorizingRealm; import org.linlinjava.litemall.admin.shiro.AdminWebSessionManager; import org.linlinjava.litemall.admin.shiro.MyAdviceFilter; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import javax.servlet.Filter; import java.util.LinkedHashMap; import java.util.Map; @Configuration public class ShiroConfig { @Bean public Realm realm() { return new AdminAuthorizingRealm(); } @Bean public ShiroLogFilter shiroLogFilter(){ return new ShiroLogFilter(); } @Bean public MyAdviceFilter myAdviceFilter() { return new MyAdviceFilter(); } @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map filters = new LinkedHashMap(); filters.put("myAdviceFilter", myAdviceFilter()); shiroFilterFactoryBean.setFilters(filters); Map filterChainDefinitionMap = new LinkedHashMap(); filterChainDefinitionMap.put("/admin/auth/login", "anon"); filterChainDefinitionMap.put("/admin/oss/upload", "anon"); filterChainDefinitionMap.put("/admin/auth/401", "anon"); filterChainDefinitionMap.put("/admin/auth/index", "anon"); filterChainDefinitionMap.put("/admin/auth/403", "anon"); filterChainDefinitionMap.put("/admin/index/index", "anon"); filterChainDefinitionMap.put("/admin/**", "authc"); shiroFilterFactoryBean.setLoginUrl("/admin/auth/401"); shiroFilterFactoryBean.setSuccessUrl("/admin/auth/index"); shiroFilterFactoryBean.setUnauthorizedUrl("/admin/auth/403"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public SessionManager sessionManager() { return new AdminWebSessionManager(); } @Bean public DefaultWebSecurityManager defaultWebSecurityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(realm()); securityManager.setSessionManager(sessionManager()); return securityManager; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } @Bean @DependsOn("lifecycleBeanPostProcessor") public static DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); creator.setProxyTargetClass(true); return creator; } } 遗留问题

在MyAdviceFilter中使用 String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));

ava.lang.IllegalStateException: getReader() has already been called for this request

shiro教程



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭